package top.buluoluo.apigateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.context.NoOpServerSecurityContextRepository;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsConfigurationSource;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import top.buluoluo.apigateway.filter.JwtAuthenticationFilter;

import java.util.Arrays;

@Configuration
@EnableReactiveMethodSecurity // 响应式方法级安全控制
@EnableWebFluxSecurity // 启用WebFluxSecurity
public class SecurityConfig {

    private final JwtAuthenticationFilter jwtAuthenticationFilter;

    public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter) {
        this.jwtAuthenticationFilter = jwtAuthenticationFilter;
    }

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        return http
                // 禁用CSRF（因为使用JWT）
                .csrf(csrf -> csrf.disable())

                // 设置CORS配置
                .cors(cors -> cors.configurationSource(corsConfigurationSource()))

                // 设置会话管理为无状态
                .securityContextRepository(NoOpServerSecurityContextRepository.getInstance())

                // 配置请求授权
                .authorizeExchange(authz -> authz
                                // 公开端点（无需认证）
                                .pathMatchers(
                                        "/user-service/auth/login",
                                        "/user-service/auth/register",
                                        "/product-service/**",
//                                "/user-service/v3/api-docs/",
                                        "/actuator/**",
                                        // Swagger UI 相关路径
                                        "/swagger-ui/**",        // Swagger UI 页面
                                        "/v3/api-docs/**",       // OpenAPI 文档
                                        "/*/v3/api-docs",           // 带服务前缀的访问
                                        "/*/v3/api-docs/**",        // 带服务前缀的所有子路
                                        "/webjars/**",           // Swagger UI 资源文件
                                        "/swagger-resources/**", // Swagger 资源
                                        "/swagger-ui.html",      // Swagger UI HTML
                                        "/favicon.ico"        // 网站图标
                                ).permitAll()

                                // 管理端点需要ADMIN角色
                                .pathMatchers("/user-service/admin/**").hasRole("ADMIN")
                                .anyExchange().authenticated()
//                                .pathMatchers("/user-service/**").authenticated()
//                                .pathMatchers("/orders-service/**").authenticated()
//                        .pathMatchers("/product-service/**").authenticated()
                )

                // 添加JWT认证过滤器（响应式方式）
                .addFilterAt(jwtAuthenticationFilter, SecurityWebFiltersOrder.AUTHENTICATION)
                .build();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList(
                "http://localhost:3000",
                "http://localhost:8080",
                "http://localhost:5173"
        ));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}